package cn.fastpay.management.handler;

import cn.fastpay.core.annotation.JsonResultIgnore;
import cn.fastpay.core.vo.ApiCommonResultVO;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author freewolf
 * 检查返回 ApiCommonResultVO 的类是否包含 JsonResultIgnore 注解
 * 这里要改递归 可以深入子类
 */
@ControllerAdvice
public class JsonFilterAdvice implements ResponseBodyAdvice<ApiCommonResultVO> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
        List<Annotation> annotations = Arrays.asList(methodParameter.getMethodAnnotations());
        return annotations.stream().anyMatch(annotation -> annotation.annotationType().equals(JsonResultIgnore.class));
    }

    @Override
    public ApiCommonResultVO beforeBodyWrite(ApiCommonResultVO resultVO, MethodParameter returnType, MediaType mediaType,
                                             Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                             ServerHttpResponse serverHttpResponse) {

        // 如果返回结果 是 BaseObject，非String类
        Object obj = resultVO.getData();
        if (obj instanceof Map) {
            JsonResultIgnore annotation = returnType.getMethodAnnotation(JsonResultIgnore.class);
            List<String> possibleFilters = Arrays.asList(annotation.keys());

            Map<String, Object> valueMap = (Map<String, Object>) obj;

            Iterator<Map.Entry<String, Object>> iterator = valueMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Object> entry = iterator.next();
                if (possibleFilters.contains(entry.getKey())) {
                    iterator.remove();
                }
            }
        }

        return resultVO;
    }
}
